<?php

namespace App\Http\Controllers;

use App\Models\Answer;
use App\Models\Category;
use App\Models\Question;
use App\Models\Test;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;

class TestController extends Controller
{
    /**
     * 考题所需字段
     *
     * @var array
     */
    public $questionColumns = [
        'id',
        'question',
        'type',
        'option_1',
        'option_2',
        'option_3',
        'option_4',
    ];

    /**
     * @return \Illuminate\Contracts\Support\Renderable|\Illuminate\Http\RedirectResponse
     */
    public function index()
    {
        /** @var User $user 考生 */
        $user = Auth::user();

        // 考试机会已用完
        abort_if(! $user->canTest(), 403,
            '您的 ' . User::MAX_TEST_NUMBER . ' 次答题机会已使用完毕，无法再次答题，感谢您的参与！'
        );

        // 正在回答的题目序号
        $index = 1;

        // 如果有考试进行中，直接获取考题，否则开始一次新的考试
        if ($test = $user->currentTest()) {
            // 超时自动交卷
            if ($test->created_at->addMinutes($test->test_time)->lt(now())) {
                $test->submit();

                return redirect()->route('score');
            }

            // 获取本次考试的考题
            $questions = Question::query()
                ->select($this->questionColumns)
                ->whereIn('id', $test->questions)
                ->get()
                ->keyBy('id');

            // 获取本次考试考生已提交的答案
            $answers = $test->answer->keyBy('question_id');

            // 按生成时的随机顺序排列，并填充已选答案
            $questions = collect($test->questions)
                ->map(function ($id) use ($questions, $answers) {
                    /** @var Question $question */
                    $question = $questions->get($id);

                    if ($question) {
                        /** @var Answer $answer */
                        $answer = $answers->get($id);

                        $question->setAttribute('user_answer', $answer ? $answer->answer : []);
                    }

                    return $question;
                });

            $index = $answers->count() + 1;
        } else {
            // 抽取考题
            $questions = $this->generateQuestions();

            // 没有考题
            abort_if(! $questions->count(), 403, '没有提取到考题，请联系管理员！');

            // 开始考试
            $test = $this->createTest($user, $questions);
        }

        // 剩余时间（秒）
        $timeLeft = $test->created_at->addMinutes($test->test_time)->diffInSeconds(now());

        // 数据：用户、考试、题目、正在回答的题目序号
        return view('test', compact('user', 'test', 'questions', 'index', 'timeLeft'));
    }

    /**
     * 根据分类随机生成考题
     *
     * @return Collection
     */
    protected function generateQuestions()
    {
        // 每种分类根据选题数随机取出
        return Category::getFromCache()->reduce(function (Collection $carry, Category $category) {
            // 当前分类未选题直接跳过
            if (! $category->selected_count) {
                return $carry;
            }

            // 按随机顺序取出当前分类选题数量的题目
            $question = $category->questions()
                ->select($this->questionColumns)
                ->inRandomOrder()
                ->limit($category->selected_count)
                ->get()
                ->sortBy('id');

            return $carry->merge($question);
        }, collect());
    }

    /**
     * 开始一次新的考试
     *
     * @param User $user
     * @param Collection $questions
     * @return Test
     */
    protected function createTest(User $user, Collection $questions)
    {
        // 获取配置
        $setting = admin_setting();

        $test = new Test();

        $test->unit_id = $user->unit_id;
        $test->question_count = $questions->count();
        $test->pre_score = $setting->get('pre_score');
        $test->test_time = $setting->get('test_time');
        $test->questions = $questions->pluck('id')->join(',');

        $user->test()->save($test);

        return $test;
    }
}
